package logic;

import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;

public class Hand {
	private Vector<Card> cardList;
	private PokerGames game;
	private int pair;
	private int secondpair;
	private int three;

	public Hand(String cards) {
		pair = 0;
		secondpair = 0;
		three = 0;
		cardList = new Vector<Card>();
		
		for(String s_card : cards.split(" ")) {
			cardList.add(new Card(s_card));
		}
		
		game = detectGame();
	}

	public Hand() {
		pair = 0;
		secondpair = 0;
		three = 0;
		cardList = new Vector<Card>();
		game = null;
	}

	public int pontos(int position) {
		return cardList.get(position).getRank();
	}

	public PokerGames getGame() {
		return game;
	}
	
	private PokerGames detectGame() {
		PokerGames game = detectSameKindGame();
		boolean isStraight = detectStraight();
		boolean isFlush = detectFlush();
		
		if(isStraight && isFlush) {
			//Can be Straight Flush or Royal Flush
			if(cardList.firstElement().getRank() == 10) {
				game = PokerGames.ROYALFLUSH;
			}else {
				game = PokerGames.STRAIGHTFLUSH;
			}
		}else if(isStraight) {
			game = PokerGames.STRAIGHT;
		}else if(isFlush) {
			game = PokerGames.FLUSH;
		}
		
		return game;
	}
	
	private boolean detectFlush() {
		char cardN = cardList.firstElement().getSuit();
		
		for(Card c : cardList) {
			if(cardN != c.getSuit()) {
				return false;
			}
		}
		
		return true;
	}

	private boolean detectStraight() {
		int cardV = cardList.firstElement().getRank();
		
		//ACE is a special case, and when it appears at the begining 
		// of sequences it means that it is a straight; 
		if(cardV == 14) {
			return true;
		}
		
		for(Card c : cardList) {
			if(cardV != c.getRank()) {
				return false;
			}			
			cardV++;
		}
		
		return true;
	}

	private PokerGames detectSameKindGame() {
		int sameCards = detectPair();
		
		if(sameCards == 1) {
			//Can be a four, triple game or a single pair
			if(detectTripleFour() == 1) {
				return PokerGames.THREEOFAKIND;
			}
			
			return PokerGames.PAIR;
		}else if(sameCards == 2) {
			int tripleOrFour = detectTripleFour();
			
			//Can be a full or two pair
			if(tripleOrFour == 1) {
				if(pair == three) {
					pair = secondpair;
				}
				return PokerGames.FULL;
			}else if(tripleOrFour == 2) {
				return PokerGames.FOUROFAKIND;
			}
			
			return PokerGames.TWOPAIR;
		}
		
		return PokerGames.SIMPLE;
	}
	
	private int detectPair() {
		Vector<Card> tempCards = new Vector<Card>();
		int cardV = 0;
		int same = 0;		
		
		tempCards.addAll(cardList);
		while(!tempCards.isEmpty()) {
			cardV = tempCards.remove(0).getRank();
			
			for(Card c : tempCards) {
				if(c.getRank() == cardV) {
					if(pair!=0) {
						secondpair = pair;
						pair = cardV;
					}
					pair = cardV;
					tempCards.remove(c);
					same++;
					break;
				}
			}
		}
		return same;
	}
	
	private int detectTripleFour() {
		Vector<Card> tempCards = new Vector<Card>();
		int cardV = 0;
		int same = 0;
		
		tempCards.addAll(cardList);
		for(int i=0; i<tempCards.size();i++) {
			same = 0;
			cardV = tempCards.remove(i).getRank();
				
			for(Card c : tempCards) {
				if(c.getRank() == cardV) {
					same++;
				}
			}
			
			if(same > 1) {
				three = cardV;
				if(same == 3) {
					return 2;
				}
				return 1;
			}
		}
		
		return 0;
	}

	public int getPair() {
		return pair;
	}

	public int getSecondPair() {
		return secondpair;
	}

	public int getThree() {
		return three;
	}

	public void addCard(Card card) {
		cardList.add(card);
	}

	public void prepare() {
		Collections.sort(cardList,new CardComparator());
		if(cardList.lastElement().getRank() == 14) {
			if(	(cardList.get(0).getRank() == 2) &&
				(cardList.get(1).getRank() == 3) &&
				(cardList.get(2).getRank() == 4) &&
				(cardList.get(3).getRank() == 5)){
				Card temp = cardList.remove(4);
				cardList.add(0, temp);
			}
		}
		game = detectGame();
	}
	
}

class CardComparator implements Comparator<Card> {

	@Override
	public int compare(Card o1, Card o2) {
		if(o1.getRank() != o2.getRank()) {
			return (o1.getRank() > o2.getRank())?1:-1;
		}
		
		return 0;
	}
	
}
